home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
linux-bo
/
etherboo.000
/
etherboo
/
etherboot-2.0
/
patches
/
netboot-freebsd-loads-linux-kernel.patch
< prev
next >
Wrap
Text File
|
1995-09-27
|
37KB
|
1,195 lines
diff -u -r -N netboot-freebsd-for-linux/3c509.c netboot-freebsd/3c509.c
--- netboot-freebsd-for-linux/3c509.c Thu Sep 7 18:58:35 1995
+++ netboot-freebsd/3c509.c Wed Sep 27 20:26:11 1995
@@ -526,7 +526,8 @@
for (i = 0; is_eeprom_busy(IS_BASE) && i < MAX_EEPROMBUSY; i++);
if (i >= MAX_EEPROMBUSY) {
- printf("3c509: eeprom failed to come ready.\r\n");
+ /* printf("3c509: eeprom failed to come ready.\r\n"); */
+ printf("3c509: eeprom is busy.\r\n"); /* memory in EPROM is tight */
return (0);
}
return (1);
diff -u -r -N netboot-freebsd-for-linux/Makefile netboot-freebsd/Makefile
--- netboot-freebsd-for-linux/Makefile Sat Sep 9 16:15:10 1995
+++ netboot-freebsd/Makefile Wed Sep 27 18:57:56 1995
@@ -6,6 +6,14 @@
# -DASK_BOOT - Ask "Boot from Network (Y/N) ?" at startup
# -DROMSIZE - Size of EPROM - Must be set (even for .COM files)
# -DRELOC - Relocation address (usually 0x90000)
+# ^^^^^^^
+# has to be changed to 0x9A000 for loading Linux kernel
+# -DPRIORIZEBOOTPKERNEL
+# - first honor the kernel name of the BOOTP reply
+# before trying defaults
+# -DBOOTPKERNELONLY
+# - never use TFTP for loading default files; the
+# BOOTP reply has to set a valid kernel name
#
# NS8390 Options:
# -DINCLUDE_WD - Include Western Digital/SMC support
@@ -21,7 +29,7 @@
PROG= nb8390.com nb3c509.com nb8390.rom nb3c509.rom
# Order is very important on the SRCS line for this prog
-SRCS= start2.S main.c misc.c bootmenu.c rpc.c
+SRCS= start2.S main.c linuxloader.c misc.c bootmenu.c rpc.c
BINDIR= /usr/mdec
BINMODE= 555
@@ -37,7 +45,7 @@
STRIP=
ROMSIZE=16384
-RELOCADDR=0x90000
+RELOCADDR=0x9A000
.SUFFIXES: .ro
diff -u -r -N netboot-freebsd-for-linux/Makefile.linux netboot-freebsd/Makefile.linux
--- netboot-freebsd-for-linux/Makefile.linux Sat Sep 9 00:23:05 1995
+++ netboot-freebsd/Makefile.linux Wed Sep 27 20:30:27 1995
@@ -6,6 +6,14 @@
# -DASK_BOOT - Ask "Boot from Network (Y/N) ?" at startup
# -DROMSIZE - Size of EPROM - Must be set (even for .COM files)
# -DRELOC - Relocation address (usually 0x90000)
+# ^^^^^^^
+# has to be changed to 0x9A000 for loading Linux kernel
+# -DPRIORIZEBOOTPKERNEL
+# - first honor the kernel name of the BOOTP reply
+# before trying defaults
+# -DBOOTPKERNELONLY
+# - never use TFTP for loading default files; the
+# BOOTP reply has to set a valid kernel name
#
# NS8390 Options:
# -DINCLUDE_WD - Include Western Digital/SMC support
@@ -22,12 +30,13 @@
PROG= nb8390.com nb3c509.com nb8390.rom nb3c509.rom
# Order is very important on the SRCS line for this prog
-SRCS= start2.S main.c misc.c bootmenu.c rpc.c
-OBJS= start2.o main.o misc.o bootmenu.o rpc.o
-ROBJS= start2.ro main.o misc.o bootmenu.o rpc.o
+SRCS= start2.S main.c linuxloader.c misc.c bootmenu.c rpc.c
+OBJS= start2.o main.o linuxloader.o misc.o bootmenu.o rpc.o
+ROBJS= start2.ro main.o linuxloader.o misc.o bootmenu.o rpc.o
CFLAGS= -O2 -DNFS -DROMSIZE=${ROMSIZE} -DRELOC=${RELOCADDR}
CFLAGS+= -fstrength-reduce -fomit-frame-pointer -m386
+CFLAGS+= -DPRIORIZEBOOTPKERNEL
# NS8390= -DINCLUDE_WD -DWD_DEFAULT_MEM=0xD0000
NS8390+= -DINCLUDE_NE
# NS8390+= -DINCLUDE_3COM -D_3COM_BASE=0x300
@@ -37,7 +46,7 @@
LDFLAGS+= -N -Ttext ${RELOCADDR} -e _start -nostdlib
ROMSIZE=16384
-RELOCADDR=0x90000
+RELOCADDR=0x9A000
.SUFFIXES: .ro
@@ -60,26 +69,22 @@
nb8390.rom: makerom start2.ro ${ROBJS} ns8390.o
${LD} ${LDFLAGS} -o nb8390.bin ${ROBJS} ns8390.o
- strip nb8390.bin
size nb8390.bin
objdump -k -q -o ${RELOCADDR} nb8390.bin >$@
./makerom $@
nb3c509.rom: makerom start2.ro ${ROBJS} 3c509.o
${LD} ${LDFLAGS} -o nb3c509.bin ${ROBJS} 3c509.o
- strip nb3c509.bin
size nb3c509.bin
objdump -k -q -o ${RELOCADDR} nb3c509.bin >$@
./makerom $@
nb8390.com: makerom start2.ro ${OBJS} ns8390.o
${LD} ${LDFLAGS} -o nb8390c.bin ${OBJS} ns8390.o
- strip nb8390c.bin
size nb8390c.bin
objdump -k -q -o ${RELOCADDR} nb8390c.bin >$@
nb3c509.com: start2.o ${OBJS} 3c509.o
${LD} ${LDFLAGS} -o nb3c509c.bin ${OBJS} 3c509.o
- strip nb3c509c.bin
size nb3c509c.bin
objdump -k -q -o ${RELOCADDR} nb3c509c.bin >$@
diff -u -r -N netboot-freebsd-for-linux/bootmenu.c netboot-freebsd/bootmenu.c
--- netboot-freebsd-for-linux/bootmenu.c Thu Sep 7 18:58:35 1995
+++ netboot-freebsd/bootmenu.c Tue Sep 26 11:34:42 1995
@@ -7,6 +7,7 @@
**************************************************************************/
#include "netboot.h"
+extern char *linux_add_cmdline();
extern struct nfs_diskless nfsdiskless;
extern int hostnamelen;
extern unsigned long netmask;
@@ -16,14 +17,14 @@
int cmd_ip(), cmd_server(), cmd_kernel(), cmd_help(), exit();
int cmd_rootfs(), cmd_swapfs(), cmd_interface(), cmd_hostname();
int cmd_netmask(), cmd_swapsize(), cmd_swapopts(), cmd_rootopts();
-int cmd_aui();
+int cmd_linuxcmd(),cmd_aui();
struct bootcmds_t {
char *name;
int (*func)();
char *help;
} bootcmds[] = {
- {"?", cmd_help, " this list"},
+/* {"?", cmd_help, " this list"}, */
{"help", cmd_help, " this list"},
{"ip", cmd_ip, "<addr> set my IP addr"},
{"server", cmd_server, "<addr> set TFTP server IP addr"},
@@ -35,6 +36,7 @@
{"swapsize", cmd_swapsize, "<nblks> set swap size"},
{"swapopts", cmd_swapopts, "<options> swap mount options"},
{"rootopts", cmd_rootopts, "<options> root mount options"},
+ {"linuxcmd", cmd_linuxcmd, "<cmds> pass cmds to linux"},
{"diskboot", exit, " boot from disk"},
{"autoboot", NULL, " continue"},
{"trans", cmd_aui, "<on|off> turn transceiver on|off"},
@@ -145,11 +147,11 @@
{
if (!setip(p, &arptable[ARP_ROOTSERVER].ipaddr)) {
printf("Root filesystem is %I:%s\r\n",
- nfsdiskless.root_saddr.sin_addr,
+ htonl(nfsdiskless.root_saddr.sin_addr.s_addr),
nfsdiskless.root_hostnam);
} else {
- bcopy(&arptable[ARP_ROOTSERVER].ipaddr,
- &nfsdiskless.root_saddr.sin_addr, 4);
+ convert_ipaddr(&nfsdiskless.root_saddr.sin_addr,
+ &arptable[ARP_ROOTSERVER].ipaddr);
while (*p && (*p != ':')) p++;
if (*p == ':') p++;
sprintf(&nfsdiskless.root_hostnam, "%s", p);
@@ -164,11 +166,11 @@
{
if (!setip(p, &arptable[ARP_SWAPSERVER].ipaddr)) {
printf("Swap filesystem is %I:%s\r\n",
- nfsdiskless.swap_saddr.sin_addr,
+ htonl(nfsdiskless.swap_saddr.sin_addr.s_addr),
nfsdiskless.swap_hostnam);
} else {
- bcopy(&arptable[ARP_SWAPSERVER].ipaddr,
- &nfsdiskless.swap_saddr.sin_addr, 4);
+ convert_ipaddr(&nfsdiskless.swap_saddr.sin_addr,
+ &arptable[ARP_SWAPSERVER].ipaddr);
while (*p && (*p != ':')) p++;
if (*p == ':') p++;
sprintf(&nfsdiskless.swap_hostnam, "%s", p);
@@ -269,6 +271,19 @@
}
/**************************************************************************
+LINUXCMD - Pass commands to linux
+**************************************************************************/
+cmd_linuxcmd(p)
+ char *p;
+{
+ if (*p)
+ linux_add_cmdline(p);
+ else
+ printf("Linux cmdline: %s\r\n",linux_add_cmdline(p));
+ return;
+}
+
+/**************************************************************************
EXECUTE - Decode command
**************************************************************************/
execute(buf)
@@ -289,7 +304,7 @@
} else
cmd++;
}
- printf("bad command - type 'help' for list\n\r");
+ printf("error: `help' for list\n\r");
return(0);
}
@@ -298,13 +313,19 @@
**************************************************************************/
bootmenu()
{
+ unsigned long time;
char cmd[80];
int ptr, c;
- printf("\r\n");
+ linux_add_cmdline(0); /* clear linux cmdline */
+ printf(" \r\n");
while (1) {
ptr = 0;
printf("boot> ");
while (ptr < 80) {
+ for (time = currticks() + 90*18; !iskey() ;)
+ if (time < currticks()) {
+ printf("autoboot\r\n");
+ goto done; }
c = getchar();
if (c == '\r')
break;
@@ -322,5 +343,6 @@
printf("\r\n");
if (execute(cmd)) break;
}
+ done:
eth_reset();
}
diff -u -r -N netboot-freebsd-for-linux/linuxloader.c netboot-freebsd/linuxloader.c
--- netboot-freebsd-for-linux/linuxloader.c Thu Jan 1 01:00:00 1970
+++ netboot-freebsd/linuxloader.c Wed Sep 27 19:44:28 1995
@@ -0,0 +1,271 @@
+/**************************************************************************
+Linux loader
+
+Author: Markus Gutschke (gutschk@math.uni-muenster.de)
+ Date: Sep/95
+
+**************************************************************************/
+
+#include "netboot.h"
+
+#define LINUX_IMAGE_ADDR ((char *)0x10000L)
+#define XTRACMDS ((char *)0x98000L)
+#define LINUX_BOOTSECTOR ((char *)0x90000L)
+#define CMDLINEMAGIC 0xA33F
+#define CMDLINE ((unsigned short *)(LINUX_BOOTSECTOR+0x20))
+#define BOOTHEADER (((boot_header_t *)0x90200L)[-1])
+#define SECTOR_SIZE 512
+#define MAGIC 0xAA55
+#define SETUP_MAGIC 0x5A5AAA55
+
+typedef struct {
+ unsigned char filler;
+ unsigned char setup_sects;
+ unsigned short int root_flags;
+ unsigned short int syssize;
+ unsigned short int swap_dev;
+ unsigned short int ram_size;
+ unsigned short int vid_mode;
+ unsigned short int root_dev;
+ unsigned short int boot_flag;
+} boot_header_t;
+
+char *bootphdr = (char *)0x99000L;
+
+char *linux_add_cmdline(char *s)
+{
+ if (!s) *XTRACMDS = '\000';
+ else if (*s) {
+ char *ptr = XTRACMDS;
+ while (*ptr) ptr++;
+ *ptr++ = ' ';
+ sprintf(ptr,"%s",s); }
+ return(XTRACMDS);
+}
+
+static int strncmp(const unsigned char *s1,const unsigned char *s2,int n)
+{
+ while (n--) {
+ if (*s1 != *s2) return(*s1 - *s2);
+ else if (!*s1) return(0);
+ else {s1++; s2++;}}
+ return(0);
+}
+
+static void linux_cmdline(char *cmdline)
+{
+ extern char *kernel;
+ extern struct nfs_diskless nfsdiskless;
+ extern unsigned long netmask;
+ char *s,*d,initargs = 0;
+
+ for (s = XTRACMDS; ;) { /* check for parameters to init */
+ if ((!*s || *s == ' ') && (initargs&1)) initargs = 2;
+ if (!*s) break;
+ if (*s == '=') {initargs &= ~1; while (*s && *s != ' ') s++;}
+ else if (*s++ != ' ') {
+ if (!(initargs&1) && !strncmp(s-1,"vga=",4)) {
+ int vga = 0;
+ d = s + 3;
+ if (!strncmp(d,"ASK",3)) vga = -3;
+ else if (!strncmp(d,"EXTENDED",8)) vga = -2;
+ else if (!strncmp(d,"NORMAL",6)) vga = -1;
+ else {
+ if (*d == '-') d++;
+ while (*d >= '0' && *d <= '9') { vga = 10*vga+*d-'0'; d++; }
+ if (s[3] == '-') vga = -vga; }
+ *((unsigned short *)(LINUX_BOOTSECTOR+506)) = vga; }
+ initargs |= 1; } }
+ for (s = nfsdiskless.root_hostnam;*s&&s[1];s++);
+ sprintf(cmdline,
+ "%sBOOT_IMAGE=" /* %I: */ "%s%s%s ramdisk=0 "
+ "nfsroot=%s,rsize=%d,wsize=%d,%s,%s "
+ "nfsaddrs=%I:%I:%I:%I:%s %s",
+ initargs&2 ? "" : "auto ",
+ /* htonl(nfsdiskless.root_saddr.sin_addr.s_addr), */
+ nfsdiskless.root_hostnam,
+ *s == '/' ? "" : "/",
+ *kernel == '/' ? kernel + 1 : kernel,
+ nfsdiskless.root_hostnam,
+ nfsdiskless.root_args.rsize,
+ nfsdiskless.root_args.wsize,
+ nfsdiskless.root_args.flags & NFSMNT_SOFT ? "soft" : "hard",
+ nfsdiskless.root_args.flags & NFSMNT_INT ? "intr" : "nointr",
+ arptable[ARP_CLIENT].ipaddr,
+ htonl(nfsdiskless.root_saddr.sin_addr.s_addr),
+ arptable[ARP_GATEWAY].ipaddr,
+ htonl(netmask),
+ nfsdiskless.my_hostnam,
+ XTRACMDS);
+ for (s = d = cmdline; ;) { /* remove multiple space characters */
+ if (*s == ' ') {while (s[1] == ' ') s++; if (!s[1]) s++;}
+ if (!(*d++ = *s++)) break; }
+ *((unsigned short *)(LINUX_BOOTSECTOR+504)) = 0; /* no ramdisk */
+ *((unsigned short *)(LINUX_BOOTSECTOR+508)) = 0x00FF; /* mount root on nfs */
+ return;
+}
+
+int load_linux(int root_mount_port,int swap_mount_port,
+ int root_nfs_port,char *kernel_handle)
+{
+ extern int jmp_bootmenu[10];
+ extern char *kernel;
+ extern void start_linux(void);
+ int err, offset, read_size, count;
+ char *addr,*cmdline;
+
+ /* Linux boot sector and setup code has to be loaded to address 0x90000 */
+ if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port, kernel_handle, 0,
+ SECTOR_SIZE,LINUX_BOOTSECTOR)) != SECTOR_SIZE) {
+ readerr:
+ printf("Unable to read %s: ",kernel);
+ nfs_err(err);
+ bootmenu:
+ longjmp(jmp_bootmenu,1);
+ }
+ if (BOOTHEADER.boot_flag != MAGIC)
+ return(0);
+ /* Boot sector contains size information for setup code */
+ offset = SECTOR_SIZE;
+ read_size = SECTOR_SIZE;
+ count = BOOTHEADER.setup_sects;
+ while (count--) {
+ if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port, kernel_handle,
+ offset, read_size, LINUX_BOOTSECTOR + offset)) !=
+ read_size) {
+ if (err < 0) {
+ goto readerr; }
+ goto bootmenu; }
+ offset += err; }
+ for (count = SECTOR_SIZE-4; *(unsigned int *)(LINUX_BOOTSECTOR-
+ SECTOR_SIZE+offset+count) !=
+ SETUP_MAGIC;)
+ if (count-- < 0)
+ goto bootmenu;
+ /* Construct Linux's command line */
+ cmdline = LINUX_BOOTSECTOR + offset;
+ CMDLINE[0] = CMDLINEMAGIC;
+ CMDLINE[1] = cmdline - LINUX_BOOTSECTOR;
+ linux_cmdline(cmdline);
+ while (*cmdline) putchar(*cmdline++);
+ printf("\r\n");
+ /* Kernel image will be loaded to address 0x10000; it will automatically
+ be relocated to 0x100000 by the setup code */
+ read_size = NFS_READ_SIZE;
+ count = 16*BOOTHEADER.syssize;
+ addr = LINUX_IMAGE_ADDR;
+ printf("Loading compressed kernel image");
+ while (count >= 16) {
+ if (read_size > count) read_size = count;
+ if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port, kernel_handle,
+ offset, read_size, addr)) != read_size) {
+ if (err < 0) goto readerr;
+ if (read_size-err >= 16)
+ goto bootmenu; }
+ if (!(offset & 0x3C00)) putchar('.');
+ offset += err;
+ count -= err;
+ addr += err; }
+ /* Linux wants to mount swapspace and rootfilesystem by itself; so unmount */
+ /* all mounted NFS filesystems */
+ nfs_umountall(ARP_ROOTSERVER, root_mount_port);
+ if (arptable[ARP_SWAPSERVER].ipaddr &&
+ arptable[ARP_SWAPSERVER].ipaddr != arptable[ARP_ROOTSERVER].ipaddr)
+ nfs_umountall(ARP_SWAPSERVER, swap_mount_port);
+ /* Linux kernel has to be started in real-mode */
+ printf(" \r\nStarting...\r\n");
+ start_linux();
+ /* printf("*** %s execute failure ***\n",kernel); */
+ goto bootmenu;
+}
+
+int linux_tftp(int block,unsigned char *data,int len)
+{
+ extern int jmp_bootmenu[10];
+ static enum {Munknown,Mlinear,Mtagged,Mreading} mode = Munknown;
+ static unsigned char *addr,*execaddr,*hdraddr;
+ static struct imgheader {
+ unsigned long magic;
+ unsigned long flags;
+ struct {unsigned short bx,ds; } location;
+ struct {unsigned short ip,cs; } execaddr; } *imgheader;
+ static struct segheader {
+ unsigned long flags;
+ unsigned long loadaddr;
+ unsigned long imglength;
+ unsigned long memlength; } *segheader;
+ static int imglen,headerlen;
+ static unsigned char *last0,*last1;
+ static int lastchunk;
+
+ if (block == 1) {
+ lastchunk = 0;
+ if (*((unsigned long *)data) == 0x1B031336l) {
+ imgheader = (struct imgheader *)((unsigned long)
+ (((unsigned short *)data)[5])*16 +
+ ((unsigned short *)data)[4]);
+ segheader = (struct segheader *)imgheader;
+ last1 = (last0 = (unsigned char *)imgheader) + 0x200;
+ bcopy(data,imgheader,len);
+ headerlen = (imgheader->flags & 0x0F)*4 +
+ (imgheader->flags & 0xF0)/4;
+ execaddr = *(unsigned char **)&imgheader->execaddr;
+ hdraddr = *(unsigned char **)&imgheader->location;
+ mode = Mtagged;
+ return(1); }
+ else if (((unsigned short *)data)[255] == 0xAA55) {
+ bcopy(data,(char *)0x7C00,len);
+ execaddr = hdraddr = (unsigned char *)0x07C00000l;
+ mode = Mlinear;
+ addr = (char *)0x10000l;
+ return(1); }
+ return(0); }
+ else {
+ int i,datalen = len;
+ if (mode == Mlinear) {
+ bcopy(data,addr,datalen);
+ if ((unsigned long)(addr += 0x200) >= 0x98000l)
+ addr = (unsigned char *)0x100000l; }
+ else if (mode == Mtagged) {
+ tag:
+ do {
+ if (lastchunk)
+ goto launch;
+ segheader = (struct segheader *)((char *)segheader + headerlen);
+ imglen = segheader->imglength;
+ headerlen = (segheader->flags & 0x0F)*4 +
+ (segheader->flags & 0xF0)/4;
+ if ((i = segheader->flags & 0x03000000l) == 0)
+ addr = (unsigned char *)segheader->loadaddr;
+ else if (i == 0x01000000l)
+ addr = last1 + segheader->loadaddr;
+ else if (i == 0x02000000l) {
+ extern unsigned short memsize(void);
+ addr = (unsigned char *)(memsize()*1024l+0x100000l)
+ - segheader->loadaddr; }
+ else
+ addr = last0 - segheader->loadaddr;
+ last1 = (last0 = addr) + segheader->memlength;
+ if (segheader->flags & 0x04000000l) lastchunk = 1;
+ } while (imglen <= 0);
+ mode = Mreading;
+ goto reading; }
+ else if (mode == Mreading) {
+ reading:
+ if ((i = imglen) > datalen) i = datalen;
+ bcopy(data,addr,i);
+ datalen -= i; data += i;
+ addr += i;
+ if ((imglen -= i) <= 0) {
+ mode = Mtagged;
+ if (datalen > 0) goto tag; }
+ return(1); }
+ else
+ return(0); }
+ if (len < 0x200) {
+ extern void xstart(char *,char *,char *);
+ launch:
+ xstart(execaddr,hdraddr,(char *)0x99000000l);
+ longjmp(jmp_bootmenu,1); }
+ return(1);
+}
diff -u -r -N netboot-freebsd-for-linux/main.c netboot-freebsd/main.c
--- netboot-freebsd-for-linux/main.c Fri Sep 8 10:59:08 1995
+++ netboot-freebsd/main.c Wed Sep 27 20:26:44 1995
@@ -28,6 +28,10 @@
extern int packetlen, rpc_id;
char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+extern int load_linux(int root_mount_port,int swap_mount_port,
+ int root_nfs_port,char *kernel_handle);
+extern int linux_tftp(int block,unsigned char *data,int len);
+
/**************************************************************************
MAIN - Kick off routine
**************************************************************************/
@@ -37,6 +41,7 @@
main()
{
+ extern char *linux_add_cmdline();
int c;
char *p;
extern char edata[], end[];
@@ -56,13 +61,14 @@
}
#endif
gateA20();
- printf("\r\nBOOTP/TFTP/NFS bootstrap loader ESC for menu\n\r");
- printf("\r\nSearching for adapter...");
+ printf("\r\nBOOTP/TFTP/NFS bootstrap loader ESC for menu\n\r"
+ "\r\nSearching for adapter...");
if (!eth_probe()) {
printf("No adapter found.\r\n");
exit(0);
}
kernel = DEFAULT_BOOTFILE;
+ linux_add_cmdline(0); /* clear linux cmdline */
while (1) {
if (setjmp(jmp_bootmenu))
bootmenu();
@@ -72,6 +78,37 @@
}
/**************************************************************************
+DOMOUNT - Try to mount FS
+**************************************************************************/
+domount(char *s,int *port,int *mount_port,char *hostnam,char *fh,int arpserver,
+ struct sockaddr_in *in_saddr,struct nfs_args *args,char *fnam,
+ char *newfh)
+{
+ int err;
+ *port = rpclookup(arpserver, PROG_NFS, 2);
+ *mount_port = rpclookup(arpserver, PROG_MOUNT, 1);
+ if ((*port == -1) || (*mount_port == -1)) {
+ printf("Unable to get %s NFS/MOUNT ports\r\n",s);
+ bootmenu:
+ longjmp(jmp_bootmenu,1); }
+ if (err = nfs_mount(arpserver, *mount_port, hostnam, fh)) {
+ printf("Unable to mount %s filesystem: ",s);
+ nfserr:
+ nfs_err(err);
+ goto bootmenu; }
+ in_saddr->sin_len = sizeof(struct sockaddr_in);
+ in_saddr->sin_family = AF_INET;
+ in_saddr->sin_port = htons(*port);
+ in_saddr->sin_addr.s_addr = htonl(arptable[arpserver].ipaddr);
+ args->timeo = 10;
+ args->retrans = 100;
+ if (err = nfs_lookup(arpserver,*port,fh,fnam,newfh)) {
+ printf("Unable to open %s: ",fnam);
+ goto nfserr; }
+ return;
+}
+
+/**************************************************************************
LOAD - Try to get booted
**************************************************************************/
load()
@@ -104,6 +141,7 @@
printf("\r\nSearching for server...\r\n");
if (!bootp()) {
printf("No Server found.\r\n");
+ bootmenu:
longjmp(jmp_bootmenu,1);
}
}
@@ -117,16 +155,31 @@
#endif
/* Now use TFTP to load configuration file */
+#if defined(PRIORIZEBOOTPKERNEL) && !defined(BOOTPKERNELONLY)
+ printf(" \r\nLoading %s... ",kernel);
+ if (!tftp(kernel)) {
+#endif
+#ifndef BOOTPKERNELONLY
sprintf(cfg,"cfg.%I",arptable[ARP_CLIENT].ipaddr);
- printf("Loading %s...\r\n",cfg);
+ printf(" \r\nLoading %s... ",cfg);
if (!tftp(cfg)) {
sprintf(cfg,"/tftpboot/cfg.%I",arptable[ARP_CLIENT].ipaddr);
- printf("Loading %s...\r\n",cfg);
+ printf(" \r\nLoading %s... ",cfg);
if (!tftp(cfg)) {
- printf("Unable to load config file.\r\n");
- longjmp(jmp_bootmenu,1);
- }
- }
+#endif
+#ifndef PRIORIZEBOOTPKERNEL
+ printf(" \r\nLoading %s... ",kernel);
+ if (!tftp(kernel)) {
+#endif
+ printf("Unable to load config file.\r\n");
+ goto bootmenu;
+#if !defined(PRIORIZEBOOTPKERNEL) || \
+ defined(PRIORIZEBOOTPKERNEL) && !defined(BOOTPKERNELONLY)
+ }
+#endif
+#ifndef BOOTPKERNELONLY
+ } }
+#endif
#ifdef MDEBUG
printf("\n=>>"); getchar();
@@ -149,7 +202,7 @@
/* Check to make sure we've got a rootfs */
if (!arptable[ARP_ROOTSERVER].ipaddr) {
printf("No ROOT filesystem server!\r\n");
- longjmp(jmp_bootmenu,1);
+ goto bootmenu;
}
/* Fill in nfsdiskless.myif */
@@ -179,79 +232,36 @@
/* Lookup NFS/MOUNTD ports for SWAP using PORTMAP */
if (arptable[ARP_SWAPSERVER].ipaddr) {
char swapfs_fh[32], swapfile[32];
- swap_nfs_port = rpclookup(ARP_SWAPSERVER, PROG_NFS, 2);
- swap_mount_port = rpclookup(ARP_SWAPSERVER, PROG_MOUNT, 1);
- if ((swap_nfs_port == -1) || (swap_mount_port == -1)) {
- printf("Unable to get SWAP NFS/MOUNT ports\r\n");
- longjmp(jmp_bootmenu,1);
- }
- if (err = nfs_mount(ARP_SWAPSERVER, swap_mount_port,
- nfsdiskless.swap_hostnam, &swapfs_fh)) {
- printf("Unable to mount SWAP filesystem: ");
- nfs_err(err);
- longjmp(jmp_bootmenu,1);
- }
sprintf(swapfile,"swap.%I",arptable[ARP_CLIENT].ipaddr);
- if (err = nfs_lookup(ARP_SWAPSERVER, swap_nfs_port,
- &swapfs_fh, swapfile, &nfsdiskless.swap_fh)) {
- printf("Unable to open %s: ",swapfile);
- nfs_err(err);
- longjmp(jmp_bootmenu,1);
- }
- nfsdiskless.swap_saddr.sin_len = sizeof(struct sockaddr_in);
- nfsdiskless.swap_saddr.sin_family = AF_INET;
- nfsdiskless.swap_saddr.sin_port = htons(swap_nfs_port);
- nfsdiskless.swap_saddr.sin_addr.s_addr =
- htonl(arptable[ARP_SWAPSERVER].ipaddr);
- nfsdiskless.swap_args.timeo = 10;
- nfsdiskless.swap_args.retrans = 100;
- }
+ domount("SWAP",&swap_nfs_port,&swap_mount_port,nfsdiskless.swap_hostnam,
+ swapfs_fh,ARP_SWAPSERVER,&nfsdiskless.swap_saddr,
+ &nfsdiskless.swap_args,swapfile,nfsdiskless.swap_fh); }
/* Lookup NFS/MOUNTD ports for ROOT using PORTMAP */
- root_nfs_port = rpclookup(ARP_ROOTSERVER, PROG_NFS, 2);
- root_mount_port = rpclookup(ARP_ROOTSERVER, PROG_MOUNT, 1);
- if ((root_nfs_port == -1) || (root_mount_port == -1)) {
- printf("Unable to get ROOT NFS/MOUNT ports\r\n");
- longjmp(jmp_bootmenu,1);
- }
- if (err = nfs_mount(ARP_ROOTSERVER, root_mount_port,
- nfsdiskless.root_hostnam, &nfsdiskless.root_fh)) {
- printf("Unable to mount ROOT filesystem: ");
- nfs_err(err);
- longjmp(jmp_bootmenu,1);
- }
- nfsdiskless.root_saddr.sin_len = sizeof(struct sockaddr_in);
- nfsdiskless.root_saddr.sin_family = AF_INET;
- nfsdiskless.root_saddr.sin_port = htons(root_nfs_port);
- nfsdiskless.root_saddr.sin_addr.s_addr =
- htonl(arptable[ARP_ROOTSERVER].ipaddr);
- nfsdiskless.root_args.timeo = 10;
- nfsdiskless.root_args.retrans = 100;
+ domount("ROOT",&root_nfs_port,&root_mount_port,nfsdiskless.root_hostnam,
+ nfsdiskless.root_fh,ARP_ROOTSERVER,&nfsdiskless.root_saddr,
+ &nfsdiskless.root_args,*kernel == '/' ? kernel+1 : kernel,
+ kernel_handle);
nfsdiskless.root_time = 0;
- if (err = nfs_lookup(ARP_ROOTSERVER, root_nfs_port,
- &nfsdiskless.root_fh, *kernel == '/' ? kernel+1 : kernel,
- &kernel_handle)) {
- printf("Unable to open %s: ",kernel);
- nfs_err(err);
- longjmp(jmp_bootmenu,1);
- }
-
/* Load the kernel using NFS */
printf("Loading %s...\r\n",kernel);
if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port, &kernel_handle, 0,
sizeof(struct exec), &head)) < 0) {
printf("Unable to read %s: ",kernel);
+ nfserr:
nfs_err(err);
- longjmp(jmp_bootmenu,1);
+ goto bootmenu;
}
- if (N_BADMAG(head)) {
+ if (N_BADMAG(head) &&
+ !load_linux(root_mount_port,swap_mount_port,
+ root_nfs_port,kernel_handle)) {
printf("Bad executable format!\r\n");
- longjmp(jmp_bootmenu, 1);
+ goto bootmenu;
}
loadpoint = (char *)0x100000;
offset = N_TXTOFF(head);
- printf("text=0x%X, ",head.a_text);
+ /* printf("text=0x%X, ",head.a_text); */
while (head.a_text > 0) {
read_size = head.a_text > NFS_READ_SIZE ?
NFS_READ_SIZE : head.a_text;
@@ -259,10 +269,10 @@
&kernel_handle, offset, read_size, loadpoint)) !=
read_size) {
if (err < 0) {
- printf("Unable to read text: ");
+ /* printf("Unable to read text: "); */
nfs_err(err);
}
- longjmp(jmp_bootmenu, 1);
+ goto bootmenu;
}
loadpoint += err;
head.a_text -= err;
@@ -270,7 +280,7 @@
}
while (((int)loadpoint) & CLOFSET)
*(loadpoint++) = 0;
- printf("data=0x%X, ",head.a_data);
+ /* printf("data=0x%X, ",head.a_data); */
while (head.a_data > 0) {
read_size = head.a_data > NFS_READ_SIZE ?
NFS_READ_SIZE : head.a_data;
@@ -278,19 +288,19 @@
&kernel_handle, offset, read_size, loadpoint)) !=
read_size) {
if (err < 0) {
- printf("Unable to read data: ");
+ /* printf("Unable to read data: "); */
nfs_err(err);
}
- longjmp(jmp_bootmenu, 1);
+ goto bootmenu;
}
loadpoint += err;
head.a_data -= err;
offset += err;
}
- printf("bss=0x%X, ",head.a_bss);
+ /* printf("bss=0x%X, ",head.a_bss); */
while(head.a_bss--) *(loadpoint++) = 0;
- printf("entry=0x%X.\n\r",head.a_entry);
+ /* printf("entry=0x%X.\n\r",head.a_entry); */
/* Jump to kernel */
bootinfo.bi_version = BOOTINFO_VERSION;
@@ -298,7 +308,7 @@
bootinfo.bi_nfs_diskless = &nfsdiskless;
kernelentry = (void *)(head.a_entry & 0x00FFFFFF);
(*kernelentry)(0,NODEV,0,0,0,&bootinfo,0,0,0);
- printf("*** %s execute failure ***\n",kernel);
+ /* printf("*** %s execute failure ***\n",kernel); */
}
/**************************************************************************
@@ -406,42 +416,50 @@
struct tftp_t *tr;
int retry = MAX_TFTP_RETRIES;
static unsigned short isocket = 2000;
- unsigned short osocket = TFTP;
- unsigned short len, block=1;
+ unsigned short osocket;
+ unsigned short len,sndlen,block=1,i;
struct tftp_t tp;
int code;
isocket++;
tp.opcode = htons(TFTP_RRQ);
- len = (sprintf((char *)tp.u.rrq,"%s%c%s",name,0,"octet")
- - ((char *)&tp)) + 1;
- while(retry--) {
- if (!udp_transmit(arptable[ARP_SERVER].ipaddr, isocket, osocket,
- len, &tp)) return(0);
- if (await_reply(AWAIT_TFTP, isocket, NULL)) {
+ sndlen = len = (sprintf((char *)tp.u.rrq,"%s%c%s",name,0,"octet")
+ - ((char *)&tp)) + 1;
+ while(block == 1 && retry--) {
+ if (!udp_transmit(arptable[ARP_SERVER].ipaddr, isocket, TFTP,
+ sndlen, &tp)) return(0);
+ while (await_reply(AWAIT_TFTP, isocket, NULL)) {
tr = (struct tftp_t *)&packet[ETHER_HDR_SIZE];
if (tr->opcode == ntohs(TFTP_ERROR)) {
printf("TFTP error %d (%s)\r\n",
- ntohs(tr->u.err.errcode),
- tr->u.err.errmsg);
- return(0);
- } /* ACK PACKET */
+ ntohs(tr->u.err.errcode),
+ tr->u.err.errmsg);
+ return(0); } /* ACK PACKET */
if (tr->opcode != ntohs(TFTP_DATA)) return(0);
+ osocket = ntohs(tr->udp.src);
tp.opcode = htons(TFTP_ACK);
tp.u.ack.block = tr->u.data.block;
- udp_transmit(arptable[ARP_SERVER].ipaddr, isocket,
- osocket, TFTP_MIN_PACKET_SIZE, &tp);
len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 4;
- if (len >= 512) {
- printf("Config file too large.\r\n");
- config_buffer[0] = 0;
- return(0);
- } else {
- bcopy(tr->u.data.download, config_buffer, len);
- config_buffer[len] = 0;
- }
- return(1);
- }
- }
+ i = ntohs(tr->u.data.block);
+ if (i < block) continue;
+ else if (i > block) return(0);
+ udp_transmit(arptable[ARP_SERVER].ipaddr, isocket,
+ osocket, sndlen = TFTP_MIN_PACKET_SIZE, &tp);
+ if (block == 1) {
+ if (len >= 512) {
+ if (((unsigned short *)tr->u.data.download)[255] != 0xAA55 &&
+ *((unsigned long *)tr->u.data.download) != 0x1B031336l) {
+ config_buffer[0] = 0;
+ return(0); }
+ else
+ printf("Tagged file format"); }
+ else {
+ bcopy(tr->u.data.download, config_buffer, len);
+ config_buffer[len] = 0;
+ return(1); } }
+ if (!linux_tftp(block++,tr->u.data.download,len)) {
+ return(0); }
+ if (len < 512)
+ return(0); } }
return(0);
}
@@ -462,8 +480,10 @@
while(retry--) {
udp_transmit(IP_BROADCAST, 0, BOOTP_SERVER,
sizeof(struct bootp_t), &bp);
- if (await_reply(AWAIT_BOOTP, 0, NULL))
- return(1);
+ if (await_reply(AWAIT_BOOTP, 0, NULL)) {
+ extern char *bootphdr;
+ bcopy(&packet[ETHER_HDR_SIZE],bootphdr,packetlen-ETHER_HDR_SIZE);
+ return(1); }
bp.bp_secs = htons((currticks()-starttime)/20);
}
return(0);
@@ -573,26 +593,18 @@
if (bcompare(p, rfc1048_cookie, 4)) { /* RFC 1048 header */
p += 4;
while(p < end) {
- switch (*p) {
- case RFC1048_PAD:
- p++;
- continue;
- case RFC1048_END:
- p = end;
- continue;
- case RFC1048_NETMASK:
- bcopy(p+2,&netmask,4);
- break;
- case RFC1048_HOSTNAME:
- bcopy(p+2, &nfsdiskless.my_hostnam, TAG_LEN(p));
- hostnamelen = (TAG_LEN(p) + 3) & ~3;
- break;
- default:
+ unsigned char c = *p;
+ if (c == RFC1048_PAD) {p++; continue;}
+ else if (c == RFC1048_END) {p = end; continue; }
+ else if (c == RFC1048_NETMASK) {bcopy(p+2,&netmask,4); }
+ else if (c == RFC1048_HOSTNAME) {
+ bcopy(p+2,&nfsdiskless.my_hostnam,TAG_LEN(p));
+ hostnamelen = (TAG_LEN(p)+3)&~3; }
+ else {
printf("Unknown RFC1048-tag ");
for(q=p;q<p+2+TAG_LEN(p);q++)
printf("%x ",*q);
- printf("\n\r");
- }
+ printf("\n\r"); }
p += TAG_LEN(p) + 2;
}
}
diff -u -r -N netboot-freebsd-for-linux/netboot.h netboot-freebsd/netboot.h
--- netboot-freebsd-for-linux/netboot.h Thu Sep 7 19:54:14 1995
+++ netboot-freebsd/netboot.h Tue Sep 26 16:55:45 1995
@@ -46,7 +46,7 @@
#endif
#ifndef TIMEOUT /* Inter-packet retry in ticks 18/sec */
-#define TIMEOUT 20
+#define TIMEOUT 30
#endif
#ifndef NULL
@@ -129,6 +129,7 @@
#define PORTMAP_LOOKUP 3
#define MOUNT_ADDENTRY 1
+#define MOUNT_UMNTALL 4
#define NFS_LOOKUP 4
#define NFS_READ 6
diff -u -r -N netboot-freebsd-for-linux/ns8390.c netboot-freebsd/ns8390.c
--- netboot-freebsd-for-linux/ns8390.c Sat Sep 9 00:23:55 1995
+++ netboot-freebsd/ns8390.c Tue Sep 26 16:57:22 1995
@@ -310,7 +310,7 @@
}
}
eth_pio_read(0, romdata, 16);
- printf("\r\nNE1000/NE2000 base 0x%x, addr ", eth_nic_base);
+ printf("\r\nNE*000 base 0x%x, addr ", eth_nic_base);
for (i=0; i<6; i++) {
printf("%b",(int)(arptable[ARP_CLIENT].node[i] = romdata[i
+ ((eth_flags & FLAG_16BIT) ? i : 0)]));
diff -u -r -N netboot-freebsd-for-linux/rpc.c netboot-freebsd/rpc.c
--- netboot-freebsd-for-linux/rpc.c Thu Sep 7 18:58:37 1995
+++ netboot-freebsd/rpc.c Wed Sep 27 20:14:38 1995
@@ -80,6 +80,37 @@
return(-1);
}
+/***************************************************************************
+
+NFS_UMNTALL: Unmount all NFS Filesystem
+
+***************************************************************************/
+nfs_umountall(server, port)
+ int server;
+ int port;
+{
+ struct rpc_t buf, *rpc;
+ char *rpcptr;
+ int retries = MAX_RPC_RETRIES;
+ rpcptr = sprintf(&buf.u.data,"%L%L%L%L%L%L%L%L%L%S%L%L%L%L%L%L%L",
+ rpc_id, MSG_CALL, 2, PROG_MOUNT, 1, MOUNT_UMNTALL,
+ 1, hostnamelen + 28,0,&nfsdiskless.my_hostnam,0,0,2,0,0,0,0);
+ while(retries--) {
+ udp_transmit(arptable[server].ipaddr, RPC_SOCKET,
+ port, rpcptr - (char *)&buf, &buf);
+ if (await_reply(AWAIT_RPC, rpc_id, NULL)) {
+ rpc = (struct rpc_t *)&packet[ETHER_HDR_SIZE];
+ if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
+ rpc->u.reply.astatus || rpc->u.reply.data[0]) {
+ rpc_err(rpc);
+ return(-(ntohl(rpc->u.reply.data[0])));
+ } else {
+ return(0);
+ }
+ }
+ }
+ return(-1);
+}
/***************************************************************************
@@ -151,7 +182,7 @@
} else {
rlen = ntohl(rpc->u.reply.data[18]);
if (len < rlen) rlen = len;
- if (len > rlen) printf("short read\r\n");
+/* if (len > rlen) printf("short read\r\n"); */
bcopy(&rpc->u.reply.data[19], buffer, rlen);
return(rlen);
}
@@ -178,10 +209,11 @@
nfs_err(err)
int err;
{
- err = -err;
- if (err == NFSERR_PERM) printf("Not owner");
- else if (err == NFSERR_NOENT) printf("No such file or directory");
- else if (err == NFSERR_ACCES) printf("Permission denied");
- else printf("Error %d",err);
- printf("\r\n");
+ printf(
+#ifndef TIGHTMEMORY
+ err == -NFSERR_PERM ? "Not owner\r\n" :
+ err == -NFSERR_NOENT ? "No such file or directory\r\n" :
+ err == -NFSERR_ACCES ? "Permission denied\r\n" :
+#endif
+ "Error %d\n\n",-err);
}
diff -u -r -N netboot-freebsd-for-linux/start2.S netboot-freebsd/start2.S
--- netboot-freebsd-for-linux/start2.S Fri Sep 8 11:04:11 1995
+++ netboot-freebsd/start2.S Wed Sep 27 19:17:53 1995
@@ -1,5 +1,9 @@
-
-#define STACKADDR 0xe000 /* Needs to be end of bss + stacksize */
+/* Stack needs to be end of bss + stacksize, but not exceeding lower 640kB */
+#if RELOC+0xE000 > 0xA0000
+#define STACKADDR (0xA0000-RELOC)
+#else
+#define STACKADDR 0xE000
+#endif
#define KERN_CODE_SEG 0x08
#define KERN_DATA_SEG 0x10
#define REAL_MODE_SEG 0x18
@@ -89,6 +93,7 @@
#endif
1:
nop
+
mov %cs,%ax
mov %ax,%ds
mov %ax,%es
@@ -98,6 +103,7 @@
mov %eax,%esp
opsize
call _real_to_prot
+
call _main
.globl _exit
.globl exit
@@ -125,8 +131,8 @@
.globl currticks
currticks:
_currticks:
- push %ebp
- mov %esp,%ebp
+/* push %ebp
+ mov %esp,%ebp */
push %ecx
push %edx
xor %edx,%edx
@@ -141,7 +147,7 @@
or %ecx,%eax
pop %edx
pop %ecx
- pop %ebp
+/* pop %ebp */
ret
/**************************************************************************
@@ -176,8 +182,8 @@
.globl getchar
getchar:
_getchar:
- push %ebp
- mov %esp,%ebp
+/* push %ebp
+ mov %esp,%ebp */
push %ebx
call _prot_to_real
movb $0x0,%ah
@@ -188,7 +194,7 @@
xor %eax,%eax
movb %bl,%al
pop %ebx
- pop %ebp
+/* pop %ebp */
ret
/**************************************************************************
@@ -198,8 +204,8 @@
.globl iskey
iskey:
_iskey:
- push %ebp
- mov %esp,%ebp
+/* push %ebp
+ mov %esp,%ebp */
push %ebx
call _prot_to_real
xor %ebx,%ebx
@@ -214,10 +220,86 @@
xor %eax,%eax
movb %bl,%al
pop %ebx
- pop %ebp
+/* pop %ebp */
ret
+
+/**************************************************************************
+MEMSIZE - Determine size of extended memory
+**************************************************************************/
+
+ .globl _memsize
+ .globl memsize
+memsize:
+_memsize:
+ push %ebx
+ call _prot_to_real
+ .byte 0xb8
+ .word 0x8800
+ int $0x15
+ mov %ax,%bx
+ opsize
+ call _real_to_prot
+ xor %eax,%eax
+ mov %bx,%ax
+ pop %ebx
+ ret
+
+/**************************************************************************
+START_LINUX - Call linux starter code (real mode)
+**************************************************************************/
+ .globl _start_linux
+ .globl start_linux
+start_linux:
+_start_linux:
+ call _prot_to_real
+ opsize
+ call 1f
+ opsize
+ call _real_to_prot
+ ret
+1: opsize
+ ljmp $0x9020,$0x0
+
+ .globl _xstart
+ .globl xstart
+
+xstart: /* FIXME: this code is rather ugly! could some x86 programmer please*/
+_xstart: /* come up with something better (I have no clue of x86 programming)*/
+ pushl %ebx
+ pushl %ecx
+ movw 12(%esp,1),%eax /* ugly self-modifying code! */
+ movw %eax,2f+2
+ movw $0x0,2f+4
+ movw 14(%esp,1),%eax
+ movw %eax,2f+6
+ movl 20(%esp,1),%ecx
+ movl 16(%esp,1),%ebx
+ call _prot_to_real
+ opsize
+ ljmp $(RELOC>>4),$1f-_romstart /* flush cache? */
+1: nop
+ opsize
+ pushl %ecx /* bootp record */
+ opsize
+ pushl %ebx /* file header */
+ opsize
+ call 2f /* return addr */
+ opsize
+ popl %eax
+ opsize
+ popl %eax
+ opsize
+ call _real_to_prot
+ popl %ecx
+ popl %ebx
+ ret
+2: opsize
+ ljmp $(RELOC>>4),$3f-_romstart
+3: opsize
+ ret
+
/*
* C library -- _setjmp, _longjmp
*